// NextUseRegAllocator.h
// A registers allocator based on Next-use

#ifndef NEXTUSEREGALLOCATOR_H
#define NEXTUSEREGALLOCATOR_H

#include "crossbit/common.h"
#include "crossbit/RegAllocator.h"
#include <vector>
#include <queue>
#include <map>
#include <deque>
#include <set>

namespace crossbit {

		// class VBlock;

		class NextUseRegAllocator : public RegAllocator {

				public:
						NextUseRegAllocator(XTUint8 num_regs, CBOfSpillIn cb_spill_in, CBOfSpillOut cb_spill_out, CBOfRegToReg cb_regtoreg) : RegAllocator(num_regs, cb_spill_in, cb_spill_out, cb_regtoreg)
						{	
						}

						virtual ~NextUseRegAllocator()
						{}

						// Allocate target register for virtual register
						virtual XTRegNum regAlloc(XTRegNum vreg, RegAccessMode mode);	        
						// Force allocate target register "expect" to "vreg"
						virtual XTRegNum regAllocForce(XTRegNum vreg, XTRegNum expect, RegAccessMode mode);
						// Force "vreg" NOT to be allocated to "except"
						virtual XTRegNum regAllocForceExcept(XTRegNum vreg, XTRegNum except, RegAccessMode mode);

						virtual void regAllocReserve(XTRegNum reg);
						virtual void regAllocRelease(XTRegNum reg);

						// this is a auxilary function used for debugging
						void printNextUseInfo();
						void unmapIfNoNextUse(XTRegNum vreg);

						virtual void init(VBlock *vb);
						virtual void phaseTask();
						void incrementVinstSeq()
						{
								++vinst_seq;
						//		UTIL::XTMemset( vreg_spilled , 0 , sizeof( vreg_spilled ) ); modified by lixiaolong,this is useless.
								for( XTRegNum i = 0 ; i < 8 ; i ++ ){
										if( ra_reg_table[i].status == ALLOCATED ){
												XTRegNum vreg = ra_reg_table[i].mapped_to;
												ra_vreg_spilled[vreg] = true;
            //printf("This is %d ALLOCATED with %d\n",i,vreg);
										}
								}
						}

				private:
						void collectNextUseInfo(VBlock *vb);

						virtual XTRegNum regSpillOut(XTRegNum vreg);

						/*typedef std::map < XTRegNum, struct RegUsage > RegUsageTable;
						  RegUsageTable ra_vreg_usg_tbl;	// virtual registers usage table
						  RegUsageTable ra_treg_usg_tbl;	// target/physical registers usage table
						  typedef std::map< XTRegNum, XTInt32 > NextUse;
						  typedef std::deque< NextUse >	  NextUseTable;
						  NextUseTable ra_next_use_tbl;

						  std::set<XTRegNum> ra_free_regs;// free registers available for allocation
						  td::vector<XTRegNum> ra_torelease_regs; // registers that will be released immediately after the current instruction's execution
						// */

						//Modified by suntingtao
						//vreg_used_list[50] is used to store the sequence of vregs used or defined in Vinst list.
						//the pair<XTInt32,RegAccessMode> stand for the sequece number and use mod(USE or DEF).
						const static XTInt32 MAX_VREG_NUM = 50;
						std::queue<std::pair<XTInt32,RegAccessMode> > ra_vreg_used_list[MAX_VREG_NUM];
						//The usage of the physical registers.
						// here 8 is the number of the register number of intel cup
						RegUsage  ra_reg_table[8];
						bool  ra_vreg_spilled[MAX_VREG_NUM];
		};

}

#endif
